package org.duiduo.common.runtime.config;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.Objects;

/**
 * Cache配置类
 *
 * @author liangze
 * @date 2024/8/7 14:52
 */
@Order(1)
@Configuration
public class CacheConfig extends CachingConfigurerSupport {

    /**
     * 缓存前缀，用于区分不同的缓存命名空间，一般以模块名或者服务名命名，这里暂时写cache
     */
    public static final String CACHE_PREFIX = "cache:";

    /**
     * 配置Redis键的序列化方式
     *
     * @return StringRedisSerializer，用于序列化和反序列化Redis中的键
     */
    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }

    /**
     * 配置Redis值的序列化方式
     *
     * @return GenericJackson2JsonRedisSerializer，使用Jackson库以JSON格式序列化和反序列化Redis中的值
     */
    private RedisSerializer<Object> valueSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

    /**
     * 配置缓存管理器，使用Redis作为缓存后端
     *
     * @param redisConnectionFactory Redis连接工厂，用于创建Redis连接
     * @return RedisCacheManager，Redis缓存管理器实例
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 配置序列化，解决乱码的问题，设置缓存名称的前缀和缓存条目的默认过期时间
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 设置键的序列化器
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                // 设置值的序列化器
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
                // 设置缓存名称的前缀
                .computePrefixWith(name -> CACHE_PREFIX + name + ":")
                // 设置缓存条目的默认过期时间为20分钟
                .entryTtl(Duration.ofMinutes(20));
        // 创建非锁定的Redis缓存写入器
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisConnectionFactory));
        // 返回Redis缓存管理器实例，使用上述配置
        return new RedisCacheManager(redisCacheWriter, config);
    }

}
